import { Steps, SourceCode } from '@theme';
import { PackageManagerTabs } from '@theme';

# 产物兼容性

本节介绍如何指定支持的目标环境。

## 语法降级

在 Rslib 中，你可以通过设置 [lib.syntax](/config/lib/syntax) 来选择 JavaScript 和 CSS 将被降级到的语法。该配置支持直接设置 ECMAScript 版本，例如 `es2015`、`es2022` 等，也支持设置 [Browserslist](https://browsersl.ist/) 的查询语法，例如 `last 2 versions`、`> 1%`、`node >= 16`、`chrome >= 80` 等。

默认情况下，syntax 被设置为 `ESNext`，这代表将仅支持主流浏览器（Chrome / Firefox / Edge / macOS Safari / iOS Safari）或 Node.js 的最新版本，具体取决于 [output.target](/config/rsbuild/output#outputtarget)。

需要注意的是，Rslib 不会读取 Browserslist 的相关配置文件（例如 `.browserslistrc` 或 `package.json` 中的 `browserslist` 字段）。你可以通过设置 [output.overrideBrowserslist](/config/rsbuild/output#outputoverridebrowserslist) 进行覆盖，该配置比 [lib.syntax](/config/lib/syntax) 拥有更高的优先级。

## Polyfill

在处理兼容性问题之前，建议了解以下背景知识，以便更好地处理相关问题。请查看有关 [语法降级和 API 降级](https://rsbuild.rs/zh/guide/advanced/browser-compatibility#%E8%AF%AD%E6%B3%95%E9%99%8D%E7%BA%A7%E5%92%8C-api-%E9%99%8D%E7%BA%A7) 的背景知识。

### 浏览器

通常，我们不需要为 npm 包注入 polyfill，这个步骤应该在 web 应用框架侧完成，但在某些场景下，我们需要注入 polyfill 以使我们的库直接在低版本浏览器中运行。

需要注意的是，这个插件不会转换你的代码语法，它只会为代码中使用的未支持函数注入 polyfill，将它们作为普通函数导入，而不是污染全局。你需要安装 [core-js-pure](https://www.npmjs.com/package/core-js-pure) 依赖。

#### 设置

polyfill 依赖于 Babel 注入 polyfill 代码，因此你需要安装 [Rsbuild Babel 插件](https://rsbuild.rs/zh/plugins/list/plugin-babel) 和 [babel-plugin-polyfill-corejs3](https://www.npmjs.com/package/babel-plugin-polyfill-corejs3) 来注入 polyfill 代码。

<PackageManagerTabs command="add @rsbuild/plugin-babel babel-plugin-polyfill-corejs3 -D" />

并安装 [core-js-pure](https://www.npmjs.com/package/core-js-pure) 作为运行时依赖代码。

<PackageManagerTabs command="add core-js-pure" />

配置 Babel 插件，设置 [targets](https://babeljs.io/docs/options#targets) 字段以指定目标浏览器版本。

```ts title="rslib.config.ts"
import { pluginBabel } from '@rsbuild/plugin-babel'; // [!code highlight]
import { defineConfig } from '@rslib/core';

export default defineConfig({
  lib: [
    {
      format: 'esm',
    },
  ],
  plugins: [
    // [!code highlight:14]
    pluginBabel({
      babelLoaderOptions: {
        plugins: [
          [
            require('babel-plugin-polyfill-corejs3'),
            {
              method: 'usage-pure',
              targets: { ie: '10' },
              version: '3.29',
            },
          ],
        ],
      },
    }),
  ],
});
```

#### 配置

更多详细信息，请查看 [babel-plugin-polyfill-corejs3](https://www.npmjs.com/package/babel-plugin-polyfill-corejs3) 文档。

### Node.js

:::tip 关于 Node Polyfill
通常，我们不需要在浏览器侧使用 Node 库。然而，在某些情况下，代码将在 Node 侧和浏览器侧运行，Node Polyfill 提供了这些 Node 库的浏览器版本 polyfill。
:::

通过使用 [@rsbuild/plugin-node-polyfill](https://github.com/rspack-contrib/rsbuild-plugin-node-polyfill)，Node 核心库的 polyfill 会自动注入到浏览器侧，允许你在浏览器侧使用这些模块。

#### 设置

Rslib 使用 [@rsbuild/plugin-node-polyfill](https://github.com/rspack-contrib/rsbuild-plugin-node-polyfill) 提供 Node Polyfill 功能。

<PackageManagerTabs command="add @rsbuild/plugin-node-polyfill -D" />

然后将其添加到插件字段中。

```ts title="rslib.config.ts"
import { defineConfig } from '@rslib/core';
import { pluginNodePolyfill } from '@rsbuild/plugin-node-polyfill';

export default defineConfig({
  lib: [{ format: 'esm' }],
  plugins: [pluginNodePolyfill()],
});
```

#### 配置

- 对于启用了 `bundle` 的项目，Node Polyfill 将被注入并包含在输出中。
- 对于未启用 `bundle` 的项目，默认情况下不会注入 polyfill。为了避免在每个模块中内联 polyfill，模块需要被 external，并手动添加到依赖中，请按照以下步骤操作：
  1. 配置 `output.external` 和 `resolvedPolyfillToModules`，你可以从 [@rsbuild/plugin-node-polyfill](https://github.com/rspack-contrib/rsbuild-plugin-node-polyfill) 导入。这将 polyfill 模块 external 到已安装的 polyfill 依赖中。
  2. 安装使用的 polyfill 模块作为依赖。

  通过以上步骤，每个 polyfill 模块的使用将被替换为 `externals` 字段中的相应模块。更多详细信息，请查看 <SourceCode href="https://github.com/web-infra-dev/rslib/blob/main/tests/integration/node-polyfill/bundle-false/rslib.config.ts" /> 的示例。

更多详细信息，请查看 [@rsbuild/plugin-node-polyfill](https://github.com/rspack-contrib/rsbuild-plugin-node-polyfill) 文档，所有配置均适用于 Rslib。
